/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipo.mm.ejb.util;

/**
 *
 * @author makcro
 */
public class MeetingSearchEJBQLQueryBuilder {

    private boolean meetingClauseAdded = false;
    private boolean orgClauseAdded = false;
    private boolean repClauseAdded = false;
    private String query;
    private String nextConditionClause = null;
    private final String meetingNameFilter;
    private final String meetingNameOper;
    private final String venueFilter;
    private final String venueOper;
    private final String conclusionsFilter;
    private final String conclusionsOper;
    private final boolean dateInterval;
    private final String orgNameFilter;
    private final String orgNameOper;
    private final String[] orgInstFilter;
    private final String[] orgITypeFilter;
    private final String[] orgIFamilyFilter;
    private final String[] orgIRegionFilter;
    private final String[] orgIdFilter;
    private final String repNameFilter;
    private final String repNameOper;
    private final String[] repInstFilter;
    private final String[] repITypeFilter;
    private final String[] repIFamilyFilter;
    private final String[] repIRegionFilter;
    private final String[] repIdFilter;
    private final String orderByFilter;
    private final boolean isCount;
    private final boolean isQuickSearch;
    private boolean searchClauseAdded = false;

    public MeetingSearchEJBQLQueryBuilder(
            String meetingNameFilter,
            String meetingNameOper,
            String venueFilter,
            String venueOper,
            String conclutionsFilter,
            String conclutionsOper,
            boolean dateInterval,
            String orgNameFilter,
            String orgNameOper,
            String[] orgInstFilter,
            String[] orgITypeFilter,
            String[] orgIFamilyFilter,
            String[] orgIRegionFilter,
            String[] orgIdFilter,
            String repNameFilter,
            String repNameOper,
            String[] repInstFilter,
            String[] repITypeFilter,
            String[] repIFamilyFilter,
            String[] repIRegionFilter,
            String[] repIdFilter,
            String orderByFilter,
            boolean isCount,
            boolean isQuickSearch) {
        this.meetingNameFilter = meetingNameFilter;
        this.meetingNameOper = meetingNameOper;
        this.venueFilter = venueFilter;
        this.venueOper = venueOper;
        this.conclusionsFilter = conclutionsFilter;
        this.conclusionsOper = conclutionsOper;
        this.dateInterval = dateInterval;
        this.orgNameFilter = orgNameFilter;
        this.orgNameOper = orgNameOper;
        this.orgInstFilter = orgInstFilter;
        this.orgITypeFilter = orgITypeFilter;
        this.orgIFamilyFilter = orgIFamilyFilter;
        this.orgIRegionFilter = orgIRegionFilter;
        this.repNameFilter = repNameFilter;
        this.repNameOper = repNameOper;
        this.repInstFilter = repInstFilter;
        this.repITypeFilter = repITypeFilter;
        this.repIFamilyFilter = repIFamilyFilter;
        this.repIRegionFilter = repIRegionFilter;
        this.orderByFilter = orderByFilter;
        this.isCount = isCount;
        this.isQuickSearch = isQuickSearch;
        this.orgIdFilter = orgIdFilter;
        this.repIdFilter = repIdFilter;


        if (this.isCount) {
            this.query = new String("SELECT COUNT(DISTINCT m) FROM Meeting m LEFT JOIN m.representativeCollection r WHERE m.deleted = false ");
        } else {
            this.query = new String("SELECT DISTINCT m FROM Meeting m LEFT JOIN FETCH m.documentCollection LEFT JOIN m.representativeCollection r WHERE m.deleted = false ");
        }


        if (this.isQuickSearch) {
            nextConditionClause = " OR ";
        } else {
            nextConditionClause = " AND";
        }


    }

    private void addSearchCluase() {
        String clause = " AND ( \n";
        query += clause;
        this.searchClauseAdded = true;

    }

    public String getQuery() {

        if (this.meetingNameFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }
            //array of name filter words
            query += "\n(";

            String eventNameExpresion = buildSimpleCondition(meetingNameFilter,
                    meetingNameOper,
                    "m",
                    "eventName");

            query += eventNameExpresion;
            query += ")\n";

        }

        if (this.venueFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }
            query += "\n(";

            String expresion = buildSimpleCondition(venueFilter,
                    venueOper,
                    "m",
                    "venue");

            query += expresion;
            query += ")\n";

        }

        if (this.conclusionsFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = buildSimpleCondition(conclusionsFilter,
                    conclusionsOper,
                    "m",
                    "conclusion");

            query += expresion;
            query += ")\n";

        }

        if (dateInterval) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }
            query += "\n(";

            String expresion = "m.date BETWEEN :startDate AND :endDate";

            query += expresion;
            query += ")\n";

        }
        if (this.orgNameFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }
            query += "\n(";

            String expresion = buildNameCondition(orgNameFilter, orgNameOper, "m.organizer");

            query += expresion;
            query += ")\n";

        }

        if (this.orgITypeFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "m.organizer.institution.type.id " + buildSetCondition(orgITypeFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.orgIFamilyFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "m.organizer.institution.family.id " + buildSetCondition(orgIFamilyFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.orgIRegionFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "m.organizer.institution.region.id " + buildSetCondition(orgIRegionFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.orgInstFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "m.organizer.institution.id " + buildSetCondition(orgInstFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.orgIdFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "m.organizer.id " + buildSetCondition(orgIdFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.repIdFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "r.id " + buildSetCondition(repIdFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.repNameFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = buildNameCondition(repNameFilter, repNameOper, "r");

            query += expresion;
            query += ")\n";

        }

        if (this.repITypeFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "r.institution.type.id " + buildSetCondition(repITypeFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.repIFamilyFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "r.institution.family.id " + buildSetCondition(repIFamilyFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.repIRegionFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "r.institution.region.id " + buildSetCondition(repIRegionFilter);

            query += expresion;
            query += ")\n";

        }

        if (this.repInstFilter != null) {
            if (!this.searchClauseAdded) {
                addSearchCluase();
            } else {
                addNextConditionClause();
            }

            query += "\n(";

            String expresion = "r.institution.id " + buildSetCondition(orgInstFilter);

            query += expresion;
            query += ")\n";

        }

        if(this.searchClauseAdded){
            String expression = " )\n";
            query += expression;
        }

        if (orderByFilter != null) {

            String orderByClause = " \nORDER BY m." + orderByFilter;
            query += orderByClause;
        }



        return query;
    }

    private String buildSetCondition(String[] filter) {
        String expresion = " IN (";
        for (int i = 0; i < filter.length; i++) {
            String value = filter[i];
            expresion += value;
            if (i != filter.length - 1) {
                expresion += ", ";
            }

        }
        expresion += ")";

        return expresion;
    }

    private String buildNameCondition(String filter,
            String filterOper, String path) {

        String expresion = "";
        String[] filters = filter.split(" ");
        for (int i = 0; i < filters.length; i++) {
            String someFilter = filters[i];

            expresion += " ( " + path + ".firstName LIKE '%" + someFilter + "%' OR " + path + ".lastName LIKE '%" + someFilter + "%')";

            if (i != filters.length - 1) {
                expresion += " " + filterOper + " ";
            }
        }

        return expresion;


    }

    private void addNextConditionClause() {

        query += nextConditionClause;
    }

    private String buildSimpleCondition(String filter,
            String filterOper,
            String entity,
            String attribute) {

        String expresion = "";
        String[] filters = filter.split(" ");



        for (int i = 0; i < filters.length; i++) {
            String someFilter = filters[i];
            expresion += " " + entity + "." + attribute + " LIKE '%" + someFilter + "%' ";
            if (i != filters.length - 1) {
                expresion += " " + filterOper + " ";
            }

        }
        return expresion;

    }
}
